#include "masterPutCycleHost.h"
#include <stdlib.h>
#define P_SEND 0xFFFFF //placeholder da modificare
#define P_ACK 0xFFFFF //placeholder da modificare
#define PACKET_SEND 0xFFFFF //placeholder da modificare

static Event onNotifyMasterAckPacketP={ON_NOTIFY_MASTER_ACK_PACKET_P,NULL};
static Event onNotifyMasterAckPacket={ON_NOTIFY_MASTER_ACK_PACKET,NULL};
static Event onNotifyMasterFail={ON_NOTIFY_MASTER_FAIL,NULL};


uint8_t packetBuilder(void* sourceBuffer,uint16_t partizione, uint8_t** indirizzoPartizione){
	// ATTENZIONE, DA SOSTITUIRE CON CODICE POLITICA GESTIONE BUFFER DATI DA INVIARE
	*indirizzoPartizione=sourceBuffer+partizione*sizeof(uint8_t)*8;
	return 8;
}
void NotifyMasterCycleHostFail(void* target){
	stateMachineDispatcher(target,&onNotifyMasterFail);
}
void NotifyMasterCycleHostPutAckPacket(void* target){
	stateMachineDispatcher(target,&onNotifyMasterAckPacket);
}
void NotifyMasterCycleHostPutAckPacketP(void* target){
	stateMachineDispatcher(target,&onNotifyMasterAckPacketP);
}
void fromPacketSendingStateToPacketSendingState(void* me){
	MasterMachine* temp=(MasterMachine*)me;
	temp->i++;
	temp->pCounter--;
}
void fromInitStateToPacketSendingState(void* me){
	MasterMachine* temp=(MasterMachine*)me;
	temp->i=0;
}
StateOutcome masterPutCycleHostFinishFailState (void* me,const Event* e){
	return EVENT_IGNORED; //da arricchire/sostituire con gestione crash comunicazione
}
StateOutcome masterPutCycleHostInitTransactionState (void* me,const Event* e){
	MasterMachine* temp=(MasterMachine*)me;
	initData* eventParser;
	switch(e->signature){
	case INIT_CODE:
	case ENTRY_CODE:
		eventParser=(initData*)(e->data);
		temp->pCounter=eventParser->pPacket;
		temp->masterBuffer=eventParser->contentBuffer;
		masterPutCycleHostInit(me,NULL,P_SEND,2,(uint8_t*)&(temp->pCounter),P_ACK,NotifyMasterCycleHostPutAckPacketP);
		return EVENT_HANDLED;
	case ON_NOTIFY_MASTER_ACK_PACKET_P:
		temp->super.passageAction=fromInitStateToPacketSendingState;
		temp->super.state=masterPutCycleHostPacketSendingState;
		return EVENT_CHANGED;
	case ON_NOTIFY_MASTER_FAIL:
		temp->super.passageAction=NULL;
		temp->super.state=masterPutCycleHostFinishFailState;
		return EVENT_CHANGED;
	default:
		return EVENT_IGNORED;
	}
}
StateOutcome masterPutCycleHostPacketSendingState (void* me,const Event* e){
	MasterMachine* temp=(MasterMachine*)me;
	uint8_t* packetSent;
	uint8_t packetSize;
	switch(e->signature){
	case ENTRY_CODE:
		packetSize=packetBuilder(temp->masterBuffer,temp->i,&packetSent);
		masterPutCycleHostInit(me,NULL,PACKET_SEND,packetSize,packetSent,P_ACK,NotifyMasterCycleHostPutAckPacket);
		return EVENT_HANDLED;
	case ON_NOTIFY_MASTER_ACK_PACKET:
		if (temp->pCounter==1){ //gestione guardia
			temp->super.passageAction=NULL;
			temp->super.state=masterPutCycleHostEndTransactionState; //altrimenti lascia inalterato lo stato di destinazione
		}
		else
			temp->super.passageAction=fromPacketSendingStateToPacketSendingState;
		return EVENT_CHANGED;
	case ON_NOTIFY_MASTER_FAIL:
		temp->super.passageAction=NULL;
		temp->super.state=masterPutCycleHostFinishFailState;
		return EVENT_CHANGED;
	default:
		return EVENT_IGNORED;
	}
}
StateOutcome masterPutCycleHostEndTransactionState (void* me,const Event* e){
	//MasterMachine* temp=(MasterMachine*)me; //decommentare all'occorrenza
	switch(e->signature){
	case ENTRY_CODE:
		//invia end msg non protetto
		return EVENT_HANDLED;
	default:
		return EVENT_IGNORED; //fine: se si vuol mandare altro bisogna reinizializzare la macchina
	}
}
void masterPutCycleHostInit(void* me,void* canPort,uint32_t msgId, uint8_t msgPayloadSize, uint8_t* msgPayload, uint32_t msgAnswer, Notifier onOk){
	MasterMachine* temp=(MasterMachine*)me;
	initTransmission(&temp->microCycleHandler,canPort,msgId,msgPayloadSize,msgPayload,msgAnswer, me, onOk, NotifyMasterCycleHostFail);
}
